<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="../../img/favicon.ico">
  <title>Event Queues - COROS Documentation</title>
  <link rel="stylesheet" href="../../css/theme.css" />
  <link rel="stylesheet" href="../../css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "Event Queues";
    var mkdocs_page_input_path = "guides/02_event_queues.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="../../js/jquery-2.1.1.min.js" defer></script>
  <script src="../../js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href="../.." class="icon icon-home"> COROS Documentation</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../..">Home</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">About</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../COPYRIGHT/">Copyright</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../LICENSE/">License</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Beginner's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../tutorials/01_getting_started/">Getting Started</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Hitchker's Guide to:</span></p>
                <ul class="current">
                    <li class="toctree-l1"><a class="reference internal" href="../01_coroutines/">Coroutines</a>
                    </li>
                    <li class="toctree-l1 current"><a class="reference internal current" href="./">Event Queues</a>
    <ul class="current">
    <li class="toctree-l2"><a class="reference internal" href="#the-basics">The basics</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#queue-management">Queue management</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#event-processing">Event processing</a>
        <ul>
    <li class="toctree-l4"><a class="reference internal" href="#the-common-behaviour">The common behaviour</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#events">Events</a>
        <ul>
    <li class="toctree-l4"><a class="reference internal" href="#low-level-api">Low-level API</a>
    </li>
    <li class="toctree-l4"><a class="reference internal" href="#high-level-api">High-level API</a>
    </li>
    <li class="toctree-l4"><a class="reference internal" href="#the-question-of-timing-and-activation">The question of timing and activation...</a>
    </li>
    <li class="toctree-l4"><a class="reference internal" href="#utility-functions">Utility functions</a>
    </li>
    <li class="toctree-l4"><a class="reference internal" href="#notes-on-callback-events">Notes on callback events</a>
    </li>
    <li class="toctree-l4"><a class="reference internal" href="#notes-on-coroutine-events">Notes on coroutine events</a>
    </li>
        </ul>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#the-advanced-stuff">The advanced stuff</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#multiply-rooted-event-queues">Multiply-rooted event queues</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#event-queues-are-first-class-entities">Event queues are first-class entities</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#tldr-summary">TL/DR Summary</a>
    </li>
    </ul>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../03_components/">Components</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technocrat's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/01_co/">co.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/02_evq/">evq.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/03_comp/">comp.h</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technomancer's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/01_coroutines/">Coroutines</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/02_event_queues/">Event Queues</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/03_porting/">Porting</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../..">COROS Documentation</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="../..">Docs</a> &raquo;</li>
    
      
        
          <li>The Hitchker's Guide to: &raquo;</li>
        
      
    
    <li>Event Queues</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h1 id="the-hitchhikers-guide-to-event-queues">The Hitchhiker's Guide to Event Queues</h1>
<p>Where coroutines are the mechanism for concurrency in COROS, through CO, the EVQ event queue system deals with several problems through a fairly simple (conceptually: the implementation gets hairy) structure:</p>
<ol>
<li>Inter-task communication.</li>
<li>Task scheduling.</li>
<li>Task priorities.</li>
</ol>
<h2 id="the-basics">The basics</h2>
<p>The <a href="../../reference/02_evq/">detailed reference</a> for EVQ looks a little bit daunting given its six data types and its approximately 20 functions and callbacks.  The functions, however, come in groups of related functionality (that in languages other than C might even be a single function) that echo each other reducing the number of <em>concepts</em> required to a far lower figure.  So let's address these groupings first.</p>
<h3 id="queue-management">Queue management</h3>
<p>Unlike most event queue or mailbox systems, EVQ is not a single, global entity (like most event queue systems: think early Windows' messaging system), but neither is it a fragmented setup with multiple independent event queues (like most so-called "mailbox" systems).  It is instead a hybrid of both of these and can be treated as either, or as something half-way in between, at need.  Because of this there are three queue management functions:</p>
<ul>
<li><code>evq_create_queue()</code></li>
<li><code>evq_attach_queue()</code></li>
<li><code>evq_detach_queue()</code></li>
</ul>
<p>The first of these does what the name on the tin says: it creates a new event queue, returning an opaque pointer used as a handle.</p>
<p>The next two are where we diverge from most event queue systems.  EVQ's event queue is a segmented, tree-structured queue.  You can create multiple queues, and you can attach them in various ways and geometries.  You can also have multiple independent trees of queues and many other such arrangements.</p>
<p>The second function above, <code>evq_attach_queue()</code>, takes a child queue and attaches it to the internal list of the parent queue's children.  Internally the engine for processing queues will process all triggered events in the current queue before processing each child, one at a time, these each doing the same recursively until there are no more children.  In this regard, if using the root node of an event tree, EVQ acts like a traditional, monolithic event queue system.  Where it differs is that events can be inserted at any sub-queue, yet be processed by any queue higher up in the tree.  Processing of events can also be done at a sub-queue level which leaves events waiting higher up in the tree unprocessed.  This pairing of capabilities allows subsystems to be decoupled while at the same time allowing for a form of priority control.</p>
<p>The final function, <code>evq_detach_queue()</code>, removes a queue <em>and all of its children</em> from the given parent queue.  This permits subsystems to be activated and deactivated at need, as well as modifying priorities and such by moving queues around.</p>
<p>A solid example might help comprehension:</p>
<pre><code class="language-C">/* create our queues */
evq_queue_t main_q = evq_create_queue();
evq_queue_t uart_q = evq_create_queue();
evq_queue_t receive_q = evq_create_queue();
evq_queue_t transmit_q = evq_create_queue();
evq_queue_t log_q = evq_create_queue();
evq_queue_t serial_q = evq_create_queue();
evq_queue_t flash_q = evq_create_queue();

/* build the queue tree for the UART subsystem */
/* then attach it to the main queue */
evq_attach_queue(uart_q, receive_q);
evq_attach_queue(uart_q, transmit_q);
evq_attach_queue(main_q, uart_q);

/* do the same for the logging subsystem */
evq_attach_queue(log_q, serial_q);
evq_attach_queue(log_q, flash_q);
evq_attach_queue(main_q, log_q);
</code></pre>
<p>At this stage we have two subsystems (uart and log) that each have two further subsystems they govern.  <code>receive_q</code> and <code>transmit_q</code> are "siblings" and both children of <code>uart_q</code>.  Similar relationships exist for <code>serial_q</code>, <code>flash_q</code>, and <code>log_q</code>.  <code>uart_q</code> and <code>log_q</code> are themselves siblings under <code>main_q</code>, the root of this particular tree, looking something like this:</p>
<pre><code class="language-text">main_q
 |
 +-- uart_q
 |    |
 |    +-- receive_q
 |    |
 |    +-- transmit_q
 |
 +-- log_q
      |
      +-- serial_q
      |
      +-- flash_q
</code></pre>
<p>When events are inserted into a queue, they go exactly there: into <strong>that</strong> queue.  So if an event were to go into <code>transmit_q</code> (we'll gloss over how this is done until later in the document), it is stored inside of <code>transmit_q</code> and not seen to any other of the <code>*_q</code> structures.  To have that event processed when it activates, one would have to process the <code>transmit_q</code> queue.</p>
<p>Or the <code>uart_q</code> queue.</p>
<p>Or the <code>main_q</code> queue.</p>
<p>Any parent processes the events, in short, of any of its children, grandchildren, etc.  This implies that <code>main_q</code>, when processing, processes all events in the system (given the current layout).</p>
<p>From this same diagram we can easily see that detaching <code>uart_q</code> stops processing events on <code>uart_q</code>, <code>receive_q</code>, and <code>transmit_q</code>.  Then attaching <code>uart_q</code> as a child of <code>log_q</code> would change the dynamics again, making an event on <code>transmit_q</code> now processed by any of <code>transmit_q</code>, <code>uart_q</code>, <code>log_q</code>, or <code>main_q</code>.</p>
<p>This flexibility of event queue arrangement permits several things that would be difficult in a monolithic event queue, and would be rigid and inflexible in a priority queue system.  For example, going with the original diagram, this following code would give use a simple priority hierarchy:</p>
<pre><code class="language-C">while (true)
{
    evq_process_one_tick(receive_q, NULL);  // highest priority: all events processed here first
    evq_process_one_tick(transmit_q, NULL); // mid priority: all events processed here next
    evq_process_one_tick(log_q, NULL);      // all logging subsystem events processed here at a low priority
    evq_process_one_tick(main_q, NULL);     // near-idle priority for housekeeping tasks, etc.
}
</code></pre>
<p>Ignoring for the moment what <code>evq_process_one_tick()</code> means, and just accepting that it processes all activated events (event posting and activation will be explained below in the section on events proper, but the short version is events activate when their timers expire) on the named queue, leads to the following order of queue processing, repeated in a loop:</p>
<ul>
<li><code>receive_q</code></li>
<li><code>transmit_q</code></li>
<li><code>log_q</code><ul>
<li><code>serial_q</code></li>
<li><code>flash_q</code></li>
</ul>
</li>
<li><code>main_q</code><ul>
<li><code>uart_q</code><ul>
<li><code>receive_q</code></li>
<li><code>transmit_q</code></li>
</ul>
</li>
<li><code>log_q</code><ul>
<li><code>serial_q</code></li>
<li><code>flash_q</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<p>The indentation is used to explain <strong>why</strong>, for example, <code>receive_q</code> is processed twice in that code (it comes from processing <code>main_q</code> -&gt; <code>uart_q</code> -&gt; <code>receive_q</code> since all subqueues are processed by parent queues).  But it is also clear from this that the timing-sensitive task of receiving data from the serial port is done first and nothing else is processed until <code>receive_q</code> has all its activated messages processed before it moves to <code>transmit_q</code> and so on down the line.</p>
<p>Or, in short, it's an intrinsic priority queuing system.  There are probably better ways to arrange and organize this, but this is left as an exercise for the end-user.  ;)</p>
<blockquote>
<p><strong>A brief note on queue processing:</strong> <em>Repetition of queues in the processing loop might cause some alarm.  It doesn't matter, however, in reality.  When we first process <code>receive_q</code>, </em>all<em> activated events are processed and as part of the processing are removed from the queue.  When that first step is completed, there are no activated events in <code>receive_q</code>.  Thus later, when <code>receive_q</code> is processed again, the odds are very high that <code>receive_q</code> has no more events to process and just returns.  If some events have been activated in between, just those new events will be processed.</em></p>
</blockquote>
<h3 id="event-processing">Event processing</h3>
<p>Of course we have that one function in the earlier sample code, <code>evq_process_one_tick()</code> that likely left a few questions.  First, what is a "tick"?  (Answer: a badly-chosen name.)  Secondly, how does such a "tick" get processed?  And third, what is that extra NULL parameter at the end?</p>
<p>So let's meet the processing functions:</p>
<ul>
<li><code>evq_process();</code></li>
<li><code>evq_process_for();</code></li>
<li><code>evq_process_one_tick();</code></li>
</ul>
<p>All three of these functions accept an <code>evq_queue_t</code> to process, and a <code>evq_idle</code> function pointer.  The second, <code>evq_process_for()</code> adds a third parameter of type <code>delay_ms</code>.  They all operate almost identically with the only difference being when they return.</p>
<h4 id="the-common-behaviour">The common behaviour</h4>
<p>When any of the <code>evq_process*()</code> functions are called, they do the following:</p>
<ul>
<li>Look at the given queue's list of queued events, examining each in turn:<ul>
<li>an event which has activated (again, this is related to timeouts) has its attendant code executed,</li>
<li>this is repeated one event at a time until all activated events have been executed;</li>
</ul>
</li>
<li>It recursively processes the events of each child tree in turn (which themselves do the same to their children);</li>
<li>Once <strong>all</strong> events in <strong>all</strong> queues of this tree have been recursively processed, the <code>evq_idle</code> function (void function with no arguments) is called if provided.</li>
</ul>
<p>Once these steps have all been completed, this is where the three functions differentiate themselves:</p>
<ul>
<li><code>evq_process_one_tick()</code> returns immediately;</li>
<li><code>evq_process_for()</code> repeats these operations in a loop until the <code>delay_ms</code> time it was given has expired;</li>
<li><code>evq_process()</code> repeats these operations in a loop forever.  It should never return (and if it does it represents a serious systems failure!).</li>
</ul>
<blockquote>
<p><strong>A note on naming:</strong> <em><code>evq_process_one_tick()</code> is admittedly not very well named.  The "tick" mentioned has nothing to do with clock ticks or any other such hardware or software constructs.  It really means <code>evq_process_once()</code>.  Unfortunately this, too, leaves questions like "does this mean only one event?" or "does this mean only one queue?" and so on.  There is no perfect name and, for better or worse, <code>evq_process_one_tick()</code> is the one that kind of grew into use.</em></p>
</blockquote>
<p>The usual use cases for these are:</p>
<ul>
<li><code>evq_process()</code> is used as the main system driver in a typical embedded system, appearing at the end of the <code>main()</code> function, after hardware is initialized and all queues are arranged, to keep the system running thereafter.</li>
<li><code>evq_process_for()</code> is intended for:<ul>
<li>systems which have to periodically interact with legacy code that is not yet converted to proper COROS applications, or,</li>
<li>for implementing things like non-blocking delays inside of event handlers.</li>
</ul>
</li>
<li><code>evq_process_one_tick()</code> is intended for:<ul>
<li>processing events in unattached queues (for which q.v. in the advanced uses section below),</li>
<li>for boosting a given queue in the hierarchy if a priority boost is needed, or,</li>
<li>other such situations.</li>
</ul>
</li>
</ul>
<p>The <code>evq_idle</code> function is there for tasks which are not extremely time-sensitive for which making a full queue to drive is perhaps too resource intensive.  For example an idle function may be useful for feeding watchdog timers.  If a task takes too long to process an event, the idle function will be starved, the watchdog will not be fed, and the system will reset.  It is important to note that for the functions which loop, the <code>evq_idle</code> function is called <strong>at the bottom of each loop</strong>, after all events have been processed, not after the loop ends.</p>
<h3 id="events">Events</h3>
<p>Event creation, posting, and activation are complicated in EVQ and unfortunately most of the complexity is essential in nature, not incidental.  And the first area of complexity (and part of the reason why EVQ has such a large API) is that there are two <strong>kinds</strong> of events:</p>
<ul>
<li>callback events; and,</li>
<li>coroutine events.</li>
</ul>
<p>All low-level API functions that involve callback events are named <code>*_fn_*()</code> (e.g. <code>evq_create_fn_event()</code>).  All low-level API functions that involve coroutine events are named <code>*_co_*()</code> (e.g. <code>evq_fill_co_event()</code>).</p>
<p>All high-level API functions that involve callback events are name <code>evq_queue_*()</code> (e.g. <code>evq_queue_now()</code>).  All high-level API functions that involve coroutine events are name <code>evq_resume_*()</code> (e.g. <code>evq_resume_every()</code>).</p>
<p>And this explanation hints at another source of complexity: there is a low-level API and a high-level API.  There is also a smattering of functions that apply to both levels, essentially a few utility functions.  The low-level API deals with the manual creation and posting of persistent events.  The high-level API deals with the more common use cases of firing dynamically allocated, posted, processed, and destroyed events.</p>
<p>The high-level API, it should be noted, is implemented in terms of the low-level API, so aside from the slight overhead costs of allocating and deallocating events (ameliorated by the use of an object pool allocator) there isn't much of a performance issue to contend with in using the high-level API for a huge increase in clarity.</p>
<p>All this being said, the complexity mentioned is conceptual only.  Once the concepts are grasped, mercifully the actual use of the API is simple.</p>
<h4 id="low-level-api">Low-level API</h4>
<p>The low-level API exists to give firm control over the lifespan of an event.  It consists of these functions:</p>
<ul>
<li><code>evq_create_fn_event()</code></li>
<li><code>evq_create_co_event()</code></li>
<li><code>evq_fill_fn_event()</code></li>
<li><code>evq_fill_co_event()</code></li>
<li><code>evq_post_event()</code></li>
</ul>
<p>Events made with the low-level API are <em>persistent</em> and will <em>not</em> be destroyed when processed in the event queue.  (They will naturally be removed from the event queue.)  In general these functions are used for making specific messages that should, for efficiency, be created in advance for quick use.  For example, an interrupt handler should really do the minimum amount of work necessary to get in, do the job, and get out.  Implicitly creating an event through the use of the high-level API (especially with the memory management involved!) is problematic.  Instead an event should be created during application initialization.  It should then be (optionally) filled in the ISR before it is posted.</p>
<p>A real-ish example would be an ADC collecting data via DMA into some raw buffers, and then when the buffers are full, signalling a processing coroutine before returning.  The code might look something like this:</p>
<pre><code class="language-C">/* somewhere in initialization */
co_t process_adc = co_create(/*elided*/);
evq_event_t adc_buffer_event = evq_create_co_event(0, 0, process_adc, NULL);
evq_queue_t adc_queue = evq_create_queue();

/* in the ISR */
evq_fill_co_event(adc_buffer_event, 0, 0, process_adc, adc_buffer);
evq_post_event(adc_queue, adc_buffer_event);
</code></pre>
<p>In this code we have a coroutine for processing ADC data.  We have created an ADC buffer full event with some default data (which we later overwrite: c.f. the note below).  And we have created an event queue for ADC event processing.  (We have elided coroutine creation parameters, the declaration of the ADC buffer, the creation of the event tree hierarchy, and the <code>evq_process*()</code> call for being out of scope.)</p>
<p>During the operation of the system, the ISR fills the adc_buffer_event with new data (most notably the adc_buffer), and then "posts" the event into the adc_queue.  The unseen <code>evq_process*()</code> function that is active when the ISR returns delivers the message.</p>
<blockquote>
<p><strong>A note on creation and filling:</strong> <em>There is redundancy, yes, between creating an event and filling an event.  In the example given, why not just create the event with the <code>adc_buffer</code> address as data instead of the two step and highly repetitive create/post pair given?  In this case, it illustrates what is needed should the ISR be doing double-buffering: sending one buffer to the event queue while adjusting the ADC to point to another.  In the end I decided it was easier, if perhaps a bit annoying, to just force </em>all<em> the parameters to be re-entered in the fill calls than to put into place a difficult and error-prone system of partial updates.</em></p>
<p><em>It should be noted, too, that not all events will have this two-stage handling.  In many cases, like error signalling, you will only establish one event and pass it each time manually.</em></p>
</blockquote>
<h4 id="high-level-api">High-level API</h4>
<p>These are the functions of the high-level API.  They are intended to capture the most common forms of events to be posted: instant one-shots, delayed one-shots, and periodic.</p>
<ul>
<li><code>evq_queue_now();</code></li>
<li><code>evq_resume_now();</code></li>
<li><code>evq_queue_in();</code></li>
<li><code>evq_resume_in();</code></li>
<li><code>evq_queue_every();</code></li>
<li><code>evq_resume_every();</code></li>
</ul>
<p>The high-level API is the more commonly used API in that it provides dynamic events that are created in situ, queued, get activated, and vanish.  There are three main flavours: <code>*_now()</code> for instantaneous one-shots, <code>*_in()</code> for delayed one-shots, and <code>*_every()</code> for periodic events.  (It should be noted that periodic events are not instantaneously activated.  They are delayed by their period, then repeated according to their period.  "Fixing" this is as trivial, should the need be found, as wrapping up a call to a <code>*_now()</code> function followed by a <code>*_every()</code> function.  After years of using COROS, however, I have never found a use case for this so never bothered.)</p>
<p>Of course, each of these has two flavours.  Callback events are made and activated with the <code>*_queue_*</code> variants and coroutine events are made and activated with the <code>*_resume_*</code> variants.</p>
<p>In all cases, however, the event is created and inserted into the provided queue.  <code>evq_queue_now()</code> for example, inserts into a queue a callback event with no delay or period.  <code>evq_resume_in()</code> inserts into a queue a coroutine event which activates after a given delay has expired.  (If the talk of timing sounds maddeningly vague, please c.f. the section entitled "The question of timing and activation..." below.)</p>
<p>MOST events will be of the fire and forget time, made extemporaneously, sent off in flight, only to destroy themselves at the finish.  The extreme dynamic nature of them is not an issue, however, because the object pool allocator used to create them re-uses heap memory instead of constantly deleting and allocating memory.  The high water mark of events in flight is rapidly reached and then memory usage ceases to grow and the heap stops fragmenting.  Only in <em>very</em> timing-sensitive cases should the low-level API be used.</p>
<h4 id="the-question-of-timing-and-activation">The question of timing and activation...</h4>
<p>In the above discussion of creating and posting events the subject of timing has been brought up but glossed over.  This is because there are two different APIs involved and discussing the timing before knowing how events are even made or queued would bring in confusion.  Now, however, the stage is appropriately set.  Let's begin by looking at the declarations of two functions from the low-level API:</p>
<pre><code class="language-C">evq_event_t evq_create_co_event(delay_ms delay, delay_ms period, co_t co, void *data);
void evq_fill_fn_event(evq_event_t e, delay_ms delay, delay_ms period, evq_callback cb, void *data);
</code></pre>
<p>Notice the <code>delay</code> and <code>period</code> parameters in these?  These are of type <code>delay_ms</code> which is an unsigned 32-bit value that counts milliseconds.  As the name would suggest, this is used for delays.</p>
<p>The <code>delay</code> parameter indicates how many milliseconds should elapse before the queued event is activated.  It is added to the current tick value (for which q.v. below) and stored with the event for the time when the event needs to be activated.  When processing events, the system checks each queued event against the current tick value.  If that tick value is equal to or greater than the tick value stored with the event, the event is activated.  Thus a delay of 0 means "activate as soon as you see this" while a delay of 100 means "in 100 milliseconds, activate this".  The activation of an event involves calling its associated callback or resuming its associated coroutine, passing in the stored data as its parameter.</p>
<p>The <code>period</code> parameter is used once an event has activated.  If the period is 0, the event is discarded from the queue (and if it's an event created with the high-level API it is deleted from memory).  Otherwise the current tick has the period added to it and the event is re-inserted.  From that point onward, every <code>period</code> milliseconds the event activates.</p>
<p>The high-level API uses the following:</p>
<ul>
<li><code>*_now()</code> functions imply a <code>delay</code> and a <code>period</code> both of 0.</li>
<li><code>*_in()</code> functions imply a <code>delay</code> of the passed-in value and a <code>period</code> of 0.</li>
<li><code>*_every()</code> functions imply a <code>delay</code> and a <code>period</code> both of the provided value.</li>
</ul>
<p>But how is the tick calculated?  The user supplies this.  The user must supply a single function:</p>
<ul>
<li><code>evq_get_tick()</code></li>
</ul>
<p>This function has the following footprint: <code>tick_ms evq_get_tick(void);</code>.  The <code>tick_ms</code> type is an unsigned 64-bit value.  The user must have some kind of timer (usually the SysTick timer) firing interrupts once every millisecond, and in the handler must atomically increment a 64-bit counter each time.  <code>evq_get_tick()</code> must return that counter each time it's called.  (Why 64-bit?  Because this way we don't have to worry about tick roll-over for about 500 million years or so.  I'm sure that one reboot every 500 million years is tolerable.  32-bit only gives us 49 days or so before roll-over which means either we have to contend with complex roll-over logic that will inevitably be bugged, or we rely on watchdogs to reboot a system that has just frozen hard.)</p>
<p>For the really deep details you'll likely want to read <a href="../../architecture/02_event_queues/"><em>The Technomancer's Guide to Event Queues</em></a> but for just generally using you just need to know about the high level functions 99% of the time, understanding what they mean.  For example:</p>
<pre><code class="language-C">/* this will immediately call the copy_dma_buffer() callback */
evq_queue_now(usart_queue, copy_dma_buffer, dma_buffer);

/* this will resume the input_co() coroutine in 5000ms */
evq_event_t evq_timeout = evq_resume_in(input_queue, input_co, INPUT_TIMEOUT)

/* this will toggle a led after 250ms, and then for every 250ms thereafter */
evq_event_t evq_blinky = evq_queue_every(led_queue, toggle_led, NULL);
</code></pre>
<h4 id="utility-functions">Utility functions</h4>
<p>The following functions can work on any event, whether the static events of the low-level API or the dynamic events of the high-level API.  There are some very strong warnings related to them, however, which means they should not be used carelessly.</p>
<ul>
<li><code>evq_query_time_remaining()</code></li>
<li><code>evq_cancel_event()</code></li>
<li><code>evq_destroy_event()</code></li>
</ul>
<p>All three of these functions do what's on the tin.</p>
<p><code>evq_query_time_remaining()</code> checks an event for how much time is remaining before it's activated.  <strong><em>DO NOT EVER TRY TO QUERY A NON-PERIODIC EVENT WHICH HAS ALREADY BEEN ACTIVATED!  THIS WILL CORRUPT MEMORY!</em></strong></p>
<p><code>evq_cancel_event()</code> cancels an event "in flight" (in the queue) before it is activated.  It does not delete the event item itself.  <strong><em>DO NOT EVER TRY TO CANCEL A NON-PERIODIC EVENT WHICH HAS ALREADY BEEN ACTIVATED!  THIS WILL CORRUPT MEMORY!</em></strong></p>
<p><code>evq_destroy_event()</code> first cancels an event in the queue, then deletes the event item.  <strong><em>NB: DO NOT EVER TRY TO DESTROY A NON-PERIODIC EVENT WHICH HAS ALREADY BEEN ACTIVATED!  THIS WILL CORRUPT MEMORY!</em></strong>  In addition, note that destroying an event after the fact is unnecessary for the one-shot types of the high-level API (<code>now</code> and <code>in</code>).  These are automatically deleted after activation by the processor.</p>
<p>The restrictions on the uses of these functions are tight and use of them needs to be very careful.  For practical purposes these functions are only safely used on events created by the low-level API or on events that are periodic.  They can never be safely used on a no-delay one-shot, and must be very carefully used on a delayed one-shot event.</p>
<h4 id="notes-on-callback-events">Notes on callback events</h4>
<p>The decision to provide two kinds of events is based on the observation that neither event type, callback or coroutine, is perfect for all use cases.  Callback events are useful for these situations:</p>
<ul>
<li>Trivial operations like toggling a LED.</li>
<li>Staged operations, like moving a DMA buffer into a processing buffer before launching a coroutine event to process it.</li>
</ul>
<p>The key to recall is that callback events <em>must</em> return quickly.  They cannot yield.  They're more useful for simple signalling from ISRs or the like, though as pointed out, too, trivial operations for which a coroutine is just too heavy are also candidates for use.</p>
<h4 id="notes-on-coroutine-events">Notes on coroutine events</h4>
<p>Most events, however, are better served by coroutine events.  Coroutines are great for message pumps, and for long-form calculations that can be periodically yielded from.  For example, where the ISR may fire a callback event to copy a DMA buffer into a processing buffer, it would then issue a coroutine event that would process the contents of the processing buffer.  They're also perfect choices for staged operations like the collection of keys in a keypad for access control.</p>
<h2 id="the-advanced-stuff">The advanced stuff</h2>
<p>What is covered above is the basic usage of event queues and, honestly, likely covers 99.44% of what most systems will ever see.  EVQ, however, can do so much more than this.  Here are some of the advanced concepts you might wish to try if you're insane in the brain.</p>
<h3 id="multiply-rooted-event-queues">Multiply-rooted event queues</h3>
<p>EVQ is tree structured, but nothing says that you have to have one tree.  Consider the possibility, for example, of a modal system.</p>
<p>What do I mean by a modal system?  Well, consider some industrial control equipment.  Perhaps you have several major ways of interacting with the system; several modes of operation:</p>
<ul>
<li>Operational mode.  The default.  The machines are running and the system is reading/actuating sensor/actuators.</li>
<li>Programming mode.  Core programs are being updated or modified, generally involving things like Flash writes, verification, debugging, etc.</li>
<li>Diagnostic mode.  Something has gone wrong and you want to look inside the guts of the system to track down what it is.</li>
<li>Idle mode.  The system is not producing, but key facilities (like power management, alerts, etc.) are still active.</li>
</ul>
<p>Trying to make a big system that covers all of these modes in a single event queue is non-trivial.  You would have to make some fairly convoluted tree architectures to leave, say, power management active in all of them but programming mode, while on the other hand shutting off the actuators that operate the 300 ton press while performing diagnostics.</p>
<p>But you can make multiple trees: One tree per mode.  Priorities can be shifted around, individual subsystems (or subsystem trees) can be attached in a sensible scheme, and when you switch modes, what you're really doing is switching the root event queue tree.  The power management queue can be in all of them except programming.  The press control queue can be removed from the loop entirely while performing diagnostics, etc.</p>
<p>This would entail using something other than <code>evq_process()</code> in your <code>main()</code>, of course, since you <em>want</em> your queue processing loop to return periodically.  You'd likely want to use <code>evq_process_for()</code> or even <code>evq_process_one_tick()</code> so that you can detect the need for a mode switch and change the queue you process.</p>
<p>Note, all of this is <em>doable</em> with a singly-rooted tree, but it's so much easier if all you have to do is prefab one tree per mode and just change the tree you're working with.</p>
<h3 id="event-queues-are-first-class-entities">Event queues are first-class entities</h3>
<p>This is the most subtle aspect of the EVQ architecture.  It arose quite by accident as well.  A little bit of history is likely in order to explain the progression.</p>
<p>EVQ began life as a simple, single event queue.  Just single long list of time-ordered events that were processed in a loop, firing them off with abandon.  Then I hit the brick wall of disabling/enabling subsystem and subsystem groups which led to verbose and error-prone code.  Fixing that led to a segmented architecture where queues were chained in order and where individual queues could be inserted and removed, thus effectively enabling and disabling them at will.  This was later changed into a tree structure (the first version was effectively an unrolled tree structure that searched a putative "tree" in depth-first order but didn't group quite the way it does now).</p>
<p>Of course to make the chained queues/tree-structured queues, queues now had to be standalone entities: actual variables (handles that were pointers to the queue data).  And that meant queues, like coroutines, were just data.  Which meant you could pass queues, which are at their core message channels, around anywhere: as parameters to functions, as data to coroutines, and as data in events.</p>
<p>And there's a name for systems composed of interacting communications channels where channels are first-class: π-calculus.  I had quite by accident stumbled into a system that supported the ability to do much of the π-calculus in real code.  In <strong><em>C</em></strong>.</p>
<p>What is the practical upshot of this?  Well it becomes clearer how this works once you read <a href="../03_components/"><em>The Hitchhiker's Guide to Components</em></a>, but the practical upshot becomes that, with suitably constructed subsystems, you can modify the message tree on the fly, permitting you to easily proxy subsystems, multiplex them, merge them, and otherwise make your systems far more flexible and configurable than would be easy to do without this capability.</p>
<p>So what practical ways can this be put to use?  Look no further than system logging.  A logging facility that has no actual logging back-end can be easily conceived of.  It just provides front-end functions for writing, say, info, warning, and error messages.  There's no implementation of any of them.  Instead you have a subsystem for, say, logging to the USART.  Another subsystem logs to the network.  Yet another keeps logs in a flash-based file system.</p>
<p>If each of these subsystems implements the same message protocol, their message queue can be passed to the system logging front-end and that front-end, when you log an info message, say, can send that info message to all of the attached back-ends.  The USART may decide it will only log warnings and errors.  The network subsystem may only flash errors up the line.  And the file system logger may choose to log everything.</p>
<p>And the user code?  Just talks to the logger without caring what goes where, while the individual logging back-ends don't care if they're getting messages straight from the user or relayed via the logging manager.</p>
<h2 id="tldr-summary">TL/DR Summary</h2>
<ol>
<li>EVQ is COROS' event queue component and forms the foundation of its communications, scheduling, and priority management system.</li>
<li>Event queues are holders of time-sorted events to be processed and are arranged in a dynamic tree structure such that parent queues can process and activate events in themselves and all their children.</li>
<li>Events qeueues, like coroutines, are first class objects which can be passed around like any other data type.</li>
<li>Events are messages sent by code to queues.</li>
<li>Events, when activated, can either be callback events, invoking a function, or coroutine events, resuming a coroutine.</li>
<li>Events can be manually constructed and have their lifetimes and contents manually managed, or they can be dynamically constructed and be ephemeral in their lifetimes.</li>
<li>Events can be optionally delayed or repeated periodically.</li>
</ol>
<p>A tree-structured event queue system operates somewhere between a single linear event queue (available in many systems) and a "mailbox" system (used in most pre-emptive RTOS designs), incorporating some of the strengths of each.</p>
<p>Going on from here, the next read should be <a href="../03_components/"><em>The Hitchhiker's Guide to Components</em></a> so that the way CO is integrated with an advanced event queue system can be explored.</p>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../03_components/" class="btn btn-neutral float-right" title="Components">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="../01_coroutines/" class="btn btn-neutral" title="Coroutines"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
      
        <span><a href="../01_coroutines/" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="../03_components/" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '../..';</script>
    <script src="../../js/theme.js" defer></script>
      <script src="../../search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
